home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
17 Bit Software 3: The Continuation
/
17-Bit_The_Continuation_Disc.iso
/
amigan
/
amigan 7
/
tracer
/
refract.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-27
|
5KB
|
291 lines
#include <math.h>
#include "MyMath.h"
#include "rtd.h"
#include "macros.h"
#include "extern.h"
int refract (r, bll)/*I've not been looking forward to commenting this
please excuse it if it is ugly. (if it was hard
to write...) */
struct ray *r;
struct ball *bll;
{
struct vector new,
norm;
struct mat trans;
struct ray ir;
FFP l,
refk (),
getcapt (),
capt,
inside ();
FFP stupid;
struct sphere ss;
/*
deal with a ray coming into the ball. figure out the normal,
and how much of the light is transmitted (capt)
*/
SV (norm, r -> org, bll -> s.cent);
norm.l = LEN (norm);
capt = getcapt (&norm, &(r -> dir), bll -> ior);
/* get the addition factor for the normal for refraction */
stupid = refk (&(norm), &(r -> dir), bll -> ior);
SCMLT (stupid, norm);
AV (ir.dir, r -> dir, norm);
MV (r -> org.x, r -> org.y, r -> org.z, ir.org);
/* now get it for reflection */
SV (norm, r -> org, bll -> s.cent);
norm.l = LEN (norm);
SCMLT (SPDiv(norm.l, SPFlt(1)), norm);
stupid = SPMul( SPFlt(2), DOT(norm, r -> dir) );
SCMLT (stupid, norm);
SV (r -> dir, r -> dir, norm);
return (
SPFix(
SPAdd(
SPMul(
SPSub(
capt,
SPFlt(1)
),
SPFlt(shade (r))
),
SPMul(
capt,
inside (&ir, bll)
)
)
)
);
}
FFP inside (r, bll)/* as above, except inside out. ior is 1.0/ior now */
struct ray *r;
struct ball *bll;
{
struct vector new,
norm;
struct mat trans;
struct ray er;
FFP findo (),
lght,
l,
refk (),
getcapt (),
capt,
stupid;
struct sphere ss;
if (++level < RLEV) {
r -> dir.l = LEN (r -> dir);
r -> dir.xzl = XZL (r -> dir);
mt (&(r -> dir), &trans);
ss.rad = bll -> s.rad;
SV (ss.cent, bll -> s.cent, r -> org);
l = findo (&trans, &ss);
MV (SPMul(l, trans.x.x),SPMul(l, trans.x.y),SPMul(l, trans.x.z),new);
AV (er.org, r -> org, new);
AV (r -> org, r -> org, new);
SV (norm, er.org, bll -> s.cent);
norm.l = LEN (norm);
r -> dir.l = LEN (r -> dir);
capt = getcapt (&norm, &(r -> dir),
SPDiv(bll -> ior, SPFlt(1) )
);
stupid = refk (&norm, &(r -> dir),
SPDiv(bll -> ior, SPFlt(1) )
);
SCMLT (stupid, norm);
AV (er.dir, norm, r -> dir);
SV (norm, r -> org, bll -> s.cent);
norm.l = LEN (norm);
SCMLT ( SPDiv( norm.l, SPFlt(1) ), norm);
stupid = SPMul( SPFlt(2), DOT (norm, r -> dir) );
SCMLT (stupid, norm);
SV (r -> dir, r -> dir, norm);
lght = SPAdd(
SPMul(
( SPSub(capt, SPFlt(1) ) ),
inside (r, bll)
),
SPMul(
capt,
SPFlt( shade (&er) )
)
);
/*
lght = (1.0 - capt) * inside (r, bll) + (capt * (double) shade (&er));
*/
} else
lght = SPFlt(0);
level--;
return (lght);
}
FFP refk (nrm, in, ior)/*gets amount of normal that has to be added to
incident ray to get the proper angle of
refraction by ancient mystical methods */
struct vector *nrm,
*in;
FFP ior;
{
FFP dt,
ln,
li,
ret;
ior = SPMul(ior, ior);
dt = DOT ((*nrm), (*in));
ln = LN2 ((*nrm));
li = LN2 ((*in));
if (SPTst(dt) < 0)
ret = SPDiv(
ln,
SPSub(
SPSqrt(
SPSub(
SPMul(
dt,
dt
),
SPMul(
ln,
SPMul(
li,
SPSub(
ior,
SPFlt(1)
)
)
)
)
),
SPNeg(dt)
)
);
/*
ret = (-dt - sqrt (dt * dt - ln * li * (1 - ior))) / ln;
*/
else
ret = SPDiv(
ln,
SPAdd(
SPSqrt(
SPSub(
SPMul(
dt,
dt
),
SPMul(
ln,
SPMul(
li,
SPSub(
ior,
SPFlt(1)
)
)
)
)
),
SPNeg(dt)
)
);
/*
ret = (-dt + sqrt (dt * dt - ln * li * (1 - ior))) / ln;
*/
return (ret);
}
FFP getcapt (nrm, dr, ior)/* gets amount of light transmitted
through ball by mystical methods mentioned
above. (see nasty physics text for details)*/
struct vector *nrm,
*dr;
FFP ior;
{
FFP dt,
cs1,
cs2,
p,
s;
dt = DOT ((*nrm), (*dr));
dt = SPDiv(
LN2 ((*dr)),
SPDiv(
LN2 ((*nrm)),
SPMul(
dt,
dt
)
)
);
cs1 = SPSqrt (dt);
cs2 = SPSqrt (
SPSub(
SPDiv(
ior,
SPSub(
dt,
SPFlt(1)
)
),
SPFlt(1)
)
);
p = SPDiv(
SPAdd(
SPMul(
ior,
cs2
),
cs1
),
cs1
);
s = SPDiv(
SPAdd(
SPMul(
ior,
cs1
),
cs2
),
cs1
);
return (
SPMul(
SPFlt(2),
SPAdd(
SPMul(p, p),
SPMul(s, s)
)
)
);
}